#include <fstream>
#include <thread>
#include <cstdio>
#include "config.hpp"
#include "httplib.h"
#include "http.hpp"

using namespace httplib;

uint image_upload_counter = 0;  // 图片计数器
uint video_upload_counter = 0; // 视频计数器

void format_http_counter()
{
    image_upload_counter = 0;
    video_upload_counter = 0;
    cout << "Http thread formatted." << endl;
}

/**
 * @brief 读取文件为二进制字符串
 * @param path 文件路径
 * @return 文件内容
 */
string read_file(const string &path)
{
    ifstream file = ifstream(path, ios::binary);
    while (!file)
    {
        cout << "file not found, waiting for 1 second" << endl;
        this_thread::sleep_for(milliseconds(1000));
        // throw runtime_error("file not found");
        file = ifstream(path, ios::binary);
    }
    string content((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
    return content;
}

/**
 * @brief 将Mat帧编码为 JPEG 格式
 * @param frame 输入的帧
 * @return 编码后的 JPEG 数据
 */
string encode_frame(Mat &frame)
{
    vector<uchar> buffer;
    vector<int> params = {IMWRITE_JPEG_QUALITY, 90}; // 设置 JPEG 压缩质量为 90%
    imencode(".jpg", frame, buffer, params);
    string encoded_frame(buffer.begin(), buffer.end());
    return encoded_frame;
}

/**
 * @brief 测试上传功能
 * @return 是否上传成功
 */
bool http_post_test()
{
    Client cli(SERVER_URL);
    // 设置连接和读写超时时间为 5 秒
    cli.set_connection_timeout(5); // 连接超时
    cli.set_read_timeout(5);       // 读取超时
    cli.set_write_timeout(5);      // 写入超时

    // string img_path = IMAGE_DIR + "image_002.jpg";
    // string img_content = read_file(img_path);
    // MultipartFormDataItems items = {
    //     {"image", img_content, "img2.jpg", "image/jpeg"},
    //     {"status", "start", "", ""}};
    string video_path = VIDEO_DIR + VIDEO_OUTPUT;
    string video_content = read_file(video_path);
    MultipartFormDataItems items = {
        {"video", video_content, "video_4.mp4", "video/mp4"},
        {"status", "start", "", ""}};

    auto res = cli.Post("/track/upload-video/", items);
    if (res)
    {
        cout << res->status << endl;
        cout << res->get_header_value("Content-Type") << endl;
        cout << res->body << endl;
        remove(video_path.c_str());
        return true;
    }
    else
    {
        cout << "error code: " << res.error() << std::endl;
        return false;
    }
}

/**
 * @brief 从缓冲区获得帧并发送帧到服务器
 */
void http_post_image()
{
    Client cli(SERVER_URL);
    // 设置连接和读写超时时间为 5 秒
    cli.set_connection_timeout(5); // 连接超时
    cli.set_read_timeout(5);       // 读取超时
    cli.set_write_timeout(5);      // 写入超时

    while (running)
    {
        if (all_frames.empty() || suspend)
        {
            continue;
        }
        // 如果缓冲区中没有帧，则跳过图片上传功能

        Mat frameToPost = all_frames[0].clone();

        image_upload_counter++;
        {
            lock_guard<mutex> lock(frame_mutex);
            all_frames.erase(all_frames.begin());
        }
        cout << "consume frame, counter:" << image_upload_counter << endl;
        cout << "frame size: " << all_frames.size() << endl;
        // 发送帧到服务器
        string image_data = encode_frame(frameToPost);
        MultipartFormDataItems items = {
            {"image", image_data, "image_" + to_string(image_upload_counter) + ".jpg", "image/jpeg"}};
        auto res = cli.Post("/detect/upload-image/", items);
        if (res)
        {
            cout << res->status << endl;
            cout << res->get_header_value("Content-Type") << endl;
            cout << res->body << endl;
        }
        else
        {
            cout << "error code: " << res.error() << std::endl;
            running = false;
        }
    }

    cli.stop();
    cout << "http image thread finished" << endl;
}

/**
 * @brief 将视频上传到服务器
 */
void http_post_video()
{
    Client cli(SERVER_URL);
    // 设置连接和读写超时时间为 5 秒
    cli.set_connection_timeout(5); // 连接超时
    cli.set_read_timeout(5);       // 读取超时
    cli.set_write_timeout(5);      // 写入超时

    string video_path = VIDEO_DIR + VIDEO_OUTPUT;

    while (running)
    {
        // 上传视频已完成
        if (video_uploaded || suspend)
        {
            continue;
        }

        // 上传新视频
        video_upload_counter++;
        if (video_upload_counter >= MAX_VIDEO_NUMBER)
        {
            running = false;
        }
        string video_path = VIDEO_DIR + VIDEO_OUTPUT + "_" + to_string(video_upload_counter) + VIDEO_EXTENSION;
        string video_content = read_file(video_path);

        MultipartFormDataItems items = {
            {"video", video_content, "video_" + to_string(video_upload_counter) + ".mp4", "video/mp4"},
            {"status", "start", "", ""}};
        auto res = cli.Post("/track/upload-video/", items);
        if (res)
        {
            cout << res->status << endl;
            cout << res->get_header_value("Content-Type") << endl;
            cout << res->body << endl;

            remove(video_path.c_str());
            cout << "Video uploaded" << endl;
            video_uploaded = true;
        }
        else
        {
            cout << "error code: " << res.error() << std::endl;
            running = false;
        }
    }

    cli.stop();
    cout << "http video thread finished" << endl;
}
